package com.ruoyi.workFlow.service.impl;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.workFlow.domain.ActWorkflowFormData;
import com.ruoyi.workFlow.domain.dto.ActivitiHighLineDTO;
import com.ruoyi.workFlow.domain.dto.HistoryDataDTO;
import com.ruoyi.workFlow.domain.dto.HistoryFormDataDTO;
import com.ruoyi.workFlow.mapper.ActWorkflowFormDataMapper;
import com.ruoyi.workFlow.service.IFormHistoryDataService;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @ClassName FormHistoryDataServiceImpl
 * @Description activiti 操作记录查询
 * @Author leizhang
 * Date 2021/11/4 3:40 下午
 * @Version 1.0
 **/
@Service
public class FormHistoryDataServiceImpl implements IFormHistoryDataService {
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;

    @Resource
    private ActWorkflowFormDataMapper actWorkflowFormDataMapper;

    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * @Description : acitivti 实例历史记录数据查询
     * @Author : leizhang
     * @Date 3:41 下午 2021/11/4
     * @param businessKey
     * @return java.util.List<com.ruoyi.workFlow.domain.dto.HistoryDataDTO>
     **/
    @Override
    public List<HistoryDataDTO> historyDataShow(String businessKey) {
        List<HistoryDataDTO> returnHistoryFromDataDTOS=new ArrayList<>();
        List<ActWorkflowFormData> actWorkflowFormData = actWorkflowFormDataMapper.selectActWorkflowFormDataByBusinessKey(businessKey);
        Map<String, List<ActWorkflowFormData>> collect = actWorkflowFormData.stream().collect(Collectors.groupingBy(ActWorkflowFormData::getTaskNodeName));
        collect.entrySet().forEach(
                entry -> {
                    HistoryDataDTO returnHistoryFromDataDTO = new HistoryDataDTO();
                    returnHistoryFromDataDTO.setTaskNodeName(entry.getValue().get(0).getTaskNodeName());
                    returnHistoryFromDataDTO.setCreateName(entry.getValue().get(0).getCreateName());
                    returnHistoryFromDataDTO.setCreatedDate(sdf.format(entry.getValue().get(0).getCreateTime()));
                    returnHistoryFromDataDTO.setFormHistoryDataDTO(entry.getValue().stream().map(awfd->new HistoryFormDataDTO(awfd.getControlName(),awfd.getControlValue())).collect(Collectors.toList()));
                    returnHistoryFromDataDTOS.add(returnHistoryFromDataDTO);
                }
        );
        List<HistoryDataDTO> collect1 = returnHistoryFromDataDTOS.stream().sorted((x, y) -> x.getCreatedDate().compareTo(y.getCreatedDate())).collect(Collectors.toList());
        return collect1;
    }

    /**
     * @Description : 实时显示
     * @Author : leizhang
     * @Date 7:59 下午 2021/11/6
     * @param instanceId
     * @return com.ruoyi.workFlow.domain.dto.ActivitiHighLineDTO
     **/
    @Override
    public ActivitiHighLineDTO gethighLine(String instanceId) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(instanceId).singleResult();
        //获取bpmnModel对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
        //因为我们这里只定义了一个Process 所以获取集合中的第一个即可
        Process process = bpmnModel.getProcesses().get(0);
        //获取所有的FlowElement信息
        Collection<FlowElement> flowElements = process.getFlowElements();
        Map<String, String> map = new HashMap<>();
        for (FlowElement flowElement : flowElements) {
            //判断是否是连线
            if (flowElement instanceof SequenceFlow) {
                SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
                String ref = sequenceFlow.getSourceRef();
                String targetRef = sequenceFlow.getTargetRef();
                map.put(ref + targetRef, sequenceFlow.getId());
            }
        }
        //获取流程实例 历史节点(全部)
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .list();
        //各个历史节点   两两组合 key
        Set<String> keyList = new HashSet<>();
        for (HistoricActivityInstance i : list) {
            for (HistoricActivityInstance j : list) {
                if (i != j) {
                    keyList.add(i.getActivityId() + j.getActivityId());
                }
            }
        }
        //高亮连线ID
        Set<String> highLine = new HashSet<>();
        keyList.forEach(s -> highLine.add(map.get(s)));
        //获取流程实例 历史节点（已完成）
        List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .finished()
                .list();
        //高亮节点ID
        Set<String> highPoint = new HashSet<>();
        listFinished.forEach(s -> highPoint.add(s.getActivityId()));
        //获取流程实例 历史节点（待办节点）
        List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .unfinished()
                .list();
        //需要移除的高亮连线
        Set<String> set = new HashSet<>();
        //待办高亮节点
        Set<String> waitingToDo = new HashSet<>();
        listUnFinished.forEach(s -> {
            waitingToDo.add(s.getActivityId());
            for (FlowElement flowElement : flowElements) {
                //判断是否是 用户节点
                if (flowElement instanceof UserTask) {
                    UserTask userTask = (UserTask) flowElement;
                    if (userTask.getId().equals(s.getActivityId())) {
                        List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
                        //因为 高亮连线查询的是所有节点  两两组合 把待办 之后  往外发出的连线 也包含进去了  所以要把高亮待办节点 之后 即出的连线去掉
                        if (outgoingFlows != null && outgoingFlows.size() > 0) {
                            outgoingFlows.forEach(a -> {
                                if (a.getSourceRef().equals(s.getActivityId())) {
                                    set.add(a.getId());
                                }
                            });
                        }
                    }
                }
            }
        });
        highLine.removeAll(set);
        Set<String> iDo = new HashSet<>(); //存放 高亮 我的办理节点
        //当前用户已完成的任务
        List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery()
//                    .taskAssignee(SecurityUtils.getUsername())
                .finished()
                .processInstanceId(instanceId).list();
        taskInstanceList.forEach(a -> iDo.add(a.getTaskDefinitionKey()));
        ActivitiHighLineDTO activitiHighLineDTO =new ActivitiHighLineDTO();
        activitiHighLineDTO.setHighPoint(highPoint);
        activitiHighLineDTO.setHighLine(highLine);
        activitiHighLineDTO.setWaitingToDo(waitingToDo);
        activitiHighLineDTO.setiDo(iDo);
        return activitiHighLineDTO;
    }

    /**
     * @Description : 历史记录保存
     * @Author : leizhang
     * @Date 2:38 下午 2021/11/8
     * @param requestParam
     * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     **/
    @Override
    public List<Map<String, Object>> getHistoryInfo(ActWorkflowFormData requestParam) {
        //获取登录用户的账号信息
        requestParam.setCreateBy(SecurityUtils.getUsername());
        if (null != requestParam.getStatus()) {
            requestParam.setControlValue(requestParam.getStatus() == 1 ? "同意":"不同意");
        }
        List<ActWorkflowFormData> historyInfo = actWorkflowFormDataMapper.getHistoryInfo(requestParam);
        Map<String, List<ActWorkflowFormData>> hisList = historyInfo.stream().collect(Collectors.groupingBy(b -> b.getProcessInstanceId()));
        Map<String,Object> mapResult = null;
        List<Map<String,Object>> resultList = Lists.newArrayList();
        for (Map.Entry<String, List<ActWorkflowFormData>> keyValue : hisList.entrySet()) {
            mapResult = Maps.newHashMap();
            for (ActWorkflowFormData data : keyValue.getValue()) {
                if (!data.getControlId().equals(mapResult.get(data.getControlId())))  {
                    mapResult.put(data.getControlId(),data.getControlValue());
                    mapResult.put("businessKey",data.getBusinessKey());
                    mapResult.put("taskNodeName",data.getTaskNodeName());
                    mapResult.put("createTime",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date)data.getCreateTime()));
                    mapResult.put("processInstanceId",data.getProcessInstanceId());
                    mapResult.put("name",data.getName());
                    mapResult.put("orderCode",data.getOrderCode());
                    mapResult.put("startTime",null == data.getStartTime() ? "" : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date)data.getStartTime()));
                    mapResult.put("processDefinitionName",data.getProcessDefinitionName());
                }
            }
            resultList.add(mapResult);
        }
        Collections.sort(resultList, new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                return o2.get("createTime").toString().compareTo(o1.get("createTime").toString());
            }
        });
        return resultList;
    }
}
